#if UNITY_EDITOR
//////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2014 Audiokinetic Inc. / All Rights Reserved
//
//////////////////////////////////////////////////////////////////////

using AudioStudio;
using System;
using System.Collections.Generic;

public class AkWwiseComponentPicker : UnityEditor.EditorWindow
{
	private static AkWwiseComponentPicker s_componentPicker;
    public delegate void OnPickerChanged(UnityEditor.SerializedProperty property, AK.Wwise.TreeView.TreeViewItem treeItem);

    private readonly AkWwiseTreeView m_treeView = new AkWwiseTreeView();
	private bool m_close;
	private UnityEditor.SerializedProperty m_WwiseObjectReference;
	private UnityEditor.SerializedObject m_serializedObject;
	private WwiseObjectType m_type;
    private Guid objectGuid;

    OnPickerChanged m_onPickerChanged;

    /// <summary>
    ///  The window to repaint after closing the picker
    /// </summary>
    public static UnityEditor.EditorWindow LastFocusedWindow = null;

	private void Update()
	{
		//Unity sometimes generates an error when the window is closed from the OnGUI function.
		//So We close it here
		if (m_close)
		{
			Close();

			if (LastFocusedWindow)
			{
				UnityEditor.EditorApplication.delayCall += LastFocusedWindow.Repaint;
				LastFocusedWindow = null;
			}
		}
	}

	private void OnGUI()
	{
		using (new UnityEngine.GUILayout.VerticalScope())
		{
			m_treeView.DisplayTreeView(AK.Wwise.TreeView.TreeViewControl.DisplayTypes.USE_SCROLL_VIEW);

			using (new UnityEngine.GUILayout.HorizontalScope("box"))
			{
				if (UnityEngine.GUILayout.Button("Ok"))
				{
					//Get the selected item
					var selectedItem = m_treeView.GetSelectedItem();

					//Check if the selected item has the correct type
					if (selectedItem != null && m_type == (selectedItem.DataContext as AkWwiseTreeView.AkTreeInfo).ObjectType)
						SetGuid(selectedItem);

					//The window can now be closed
					m_close = true;
				}
				else if (UnityEngine.GUILayout.Button("Cancel"))
					m_close = true;
				else if (UnityEngine.GUILayout.Button("Reset"))
				{
					ResetGuid();
					m_close = true;
				}
				else if (UnityEngine.Event.current.type == UnityEngine.EventType.Used && m_treeView.LastDoubleClickedItem != null &&
				         m_type == (m_treeView.LastDoubleClickedItem.DataContext as AkWwiseTreeView.AkTreeInfo).ObjectType)
				{
					//We must be in 'used' mode in order for this to work
					SetGuid(m_treeView.LastDoubleClickedItem);
					m_close = true;
				}
			}
		}
	}

	private void SetGuid(AK.Wwise.TreeView.TreeViewItem in_item)
	{
        m_WwiseObjectReference.serializedObject.Update();

        //         Guid guid = Guid.Empty;
        //         if (in_item != null)
        //         {
        //             guid = new Guid((in_item.DataContext as AkWwiseTreeView.AkTreeInfo).Guid.ToByteArray());
        //         }
        //         var guidProperty = m_WwiseObjectReference.FindPropertyRelative("valueGuid.Array");
        //         AkUtilities.SetByteArrayProperty(guidProperty, guid.ToByteArray());
        //         
        //         string name = in_item.Header;
        //         uint Id = AkUtilities.ShortIDGenerator.Compute(name);
        //         uint GroupId = 0;
        //         string GroupName = string.Empty;
        // 
        //         if (guid != null)
        //         {
        //             if (m_type == WwiseObjectType.State || m_type == WwiseObjectType.Switch)
        //             {
        //                 if (in_item != null && in_item.Parent != null)
        //                 {
        //                     var groupGuid = new Guid((in_item.Parent.DataContext as AkWwiseTreeView.AkTreeInfo).Guid.ToByteArray());
        //                     List<AkWwiseProjectData.GroupValWorkUnit> list;
        //                     if (m_type == WwiseObjectType.State)
        //                         list = AkWwiseProjectInfo.GetData().StateWwu;
        //                     else
        //                         list = AkWwiseProjectInfo.GetData().SwitchWwu;
        // 
        //                     for (int i = 0; i < list.Count; i++)
        //                     {
        //                         var group = list[i].List.Find(x => x.Guid.Equals(groupGuid));
        // 
        //                         if (group != null)
        //                         {
        //                             GroupId = group.Id;
        //                             GroupName = group.Name;
        //                             break;
        //                         }
        //                     }
        //                 }
        //             }
        //             m_WwiseObjectReference.FindPropertyRelative("Id").longValue = Id;
        //             m_WwiseObjectReference.FindPropertyRelative("Name").stringValue = name;
        //             if (m_WwiseObjectReference.FindPropertyRelative("GroupId") != null)
        //                 m_WwiseObjectReference.FindPropertyRelative("GroupId").longValue = GroupId;
        //             if (m_WwiseObjectReference.FindPropertyRelative("GroupName") != null)
        //                 m_WwiseObjectReference.FindPropertyRelative("GroupName").stringValue = GroupName;
        //         }
        //         else
        //         {
        //             m_WwiseObjectReference.FindPropertyRelative("Id").longValue = 0;
        //             m_WwiseObjectReference.FindPropertyRelative("Name").stringValue = string.Empty;
        //             if (m_WwiseObjectReference.FindPropertyRelative("GroupId") != null)
        //                 m_WwiseObjectReference.FindPropertyRelative("GroupId").longValue = 0;
        //             if (m_WwiseObjectReference.FindPropertyRelative("GroupName") != null)
        //                 m_WwiseObjectReference.FindPropertyRelative("GroupName").stringValue = string.Empty;
        //         }

        if (m_onPickerChanged != null)
        {
            m_onPickerChanged(m_WwiseObjectReference, in_item);
        }

        m_WwiseObjectReference.serializedObject.ApplyModifiedProperties();
	}

	private void ResetGuid()
	{
        m_WwiseObjectReference.serializedObject.Update();
        //         m_WwiseObjectReference.FindPropertyRelative("Id").longValue = 0;
        //         m_WwiseObjectReference.FindPropertyRelative("Name").stringValue = string.Empty;
        //         if (m_WwiseObjectReference.FindPropertyRelative("GroupId") != null)
        //             m_WwiseObjectReference.FindPropertyRelative("GroupId").longValue = 0; ;
        //         if (m_WwiseObjectReference.FindPropertyRelative("GroupName") != null)
        //             m_WwiseObjectReference.FindPropertyRelative("GroupName").stringValue = string.Empty;
        //         byte[] guid = new byte[16];
        //         AkUtilities.SetByteArrayProperty(m_WwiseObjectReference.FindPropertyRelative("valueGuid.Array"), guid);

        if (m_onPickerChanged != null)
        {
            m_onPickerChanged(m_WwiseObjectReference, null);
        }

        m_WwiseObjectReference.serializedObject.ApplyModifiedProperties();
    }

	public class PickerCreator
	{
		public UnityEditor.SerializedProperty wwiseObjectReference;
		public WwiseObjectType objectType;
		public UnityEngine.Rect pickerPosition;
		public UnityEditor.SerializedObject serializedObject;
        public OnPickerChanged onPickerChanged;

		internal PickerCreator()
		{
			UnityEditor.EditorApplication.delayCall += DelayCall;
		}

		private void DelayCall()
		{
			if (s_componentPicker != null)
				return;

			s_componentPicker = CreateInstance<AkWwiseComponentPicker>();

			//position the window below the button
			var pos = new UnityEngine.Rect(pickerPosition.x, pickerPosition.yMax, 0, 0);

			//If the window gets out of the screen, we place it on top of the button instead
			if (pickerPosition.yMax > UnityEngine.Screen.currentResolution.height / 2)
				pos.y = pickerPosition.y - UnityEngine.Screen.currentResolution.height / 2;

			//We show a drop down window which is automatically destroyed when focus is lost
			s_componentPicker.ShowAsDropDown(pos,
				new UnityEngine.Vector2(pickerPosition.width >= 250 ? pickerPosition.width : 250,
					UnityEngine.Screen.currentResolution.height / 2));

			s_componentPicker.m_WwiseObjectReference = wwiseObjectReference;
			s_componentPicker.m_serializedObject = serializedObject;
			s_componentPicker.m_type = objectType;
            s_componentPicker.m_onPickerChanged = onPickerChanged;
			//Make a backup of the tree's expansion status and replace it with an empty list to make sure nothing will get expanded
			//when we populate the tree 
			var expandedItemsBackUp = AkWwiseProjectInfo.GetData().ExpandedItems;
			AkWwiseProjectInfo.GetData().ExpandedItems = new System.Collections.Generic.List<string>();

			s_componentPicker.m_treeView.AssignDefaults();
			s_componentPicker.m_treeView.SetRootItem(
				System.IO.Path.GetFileNameWithoutExtension(WwiseSetupWizard.Settings.WwiseProjectPath), WwiseObjectType.Project);

			//Populate the tree with the correct type
			switch (objectType)
			{
				case WwiseObjectType.AuxBus:
					s_componentPicker.m_treeView.PopulateItem(s_componentPicker.m_treeView.RootItem, "Auxiliary Busses",
						AkWwiseProjectInfo.GetData().AuxBusWwu);
					break;

				case WwiseObjectType.Event:
					s_componentPicker.m_treeView.PopulateItem(s_componentPicker.m_treeView.RootItem, "Events",
						AkWwiseProjectInfo.GetData().EventWwu);
					break;

				case WwiseObjectType.Soundbank:
					s_componentPicker.m_treeView.PopulateItem(s_componentPicker.m_treeView.RootItem, "Banks",
						AkWwiseProjectInfo.GetData().BankWwu);
					break;

				case WwiseObjectType.State:
					s_componentPicker.m_treeView.PopulateItem(s_componentPicker.m_treeView.RootItem, "States",
						AkWwiseProjectInfo.GetData().StateWwu);
					break;

				case WwiseObjectType.Switch:
					s_componentPicker.m_treeView.PopulateItem(s_componentPicker.m_treeView.RootItem, "Switches",
						AkWwiseProjectInfo.GetData().SwitchWwu);
					break;

				case WwiseObjectType.GameParameter:
					s_componentPicker.m_treeView.PopulateItem(s_componentPicker.m_treeView.RootItem, "Game Parameters",
						AkWwiseProjectInfo.GetData().RtpcWwu);
					break;

				case WwiseObjectType.Trigger:
					s_componentPicker.m_treeView.PopulateItem(s_componentPicker.m_treeView.RootItem, "Triggers",
						AkWwiseProjectInfo.GetData().TriggerWwu);
					break;

				case WwiseObjectType.AcousticTexture:
					s_componentPicker.m_treeView.PopulateItem(s_componentPicker.m_treeView.RootItem, "Virtual Acoustics",
						AkWwiseProjectInfo.GetData().AcousticTextureWwu);
					break;
			}

			AK.Wwise.TreeView.TreeViewItem item = null;

            byte[] byteArray = AkUtilities.GetByteArrayProperty(wwiseObjectReference.FindPropertyRelative("valueGuid.Array"));
            if (byteArray != null)
                item = s_componentPicker.m_treeView.GetItemByGuid(new Guid(byteArray));

            if (item != null)
			{
				item.ParentControl.SelectedItem = item;

				var itemIndexFromRoot = 0;

				//Expand all the parents of the selected item.
				//Count the number of items that are displayed before the selected item
				while (true)
				{
					item.IsExpanded = true;

					if (item.Parent != null)
					{
						itemIndexFromRoot += item.Parent.Items.IndexOf(item) + 1;
						item = item.Parent;
					}
					else
						break;
				}

				//Scroll down the window to make sure that the selected item is always visible when the window opens
				//there seems to be 1 pixel between each item so we add 2 pixels(top and bottom) 
				var itemHeight = item.ParentControl.m_skinSelected.button.CalcSize(new UnityEngine.GUIContent(item.Header)).y + 2.0f;
				s_componentPicker.m_treeView.SetScrollViewPosition(new UnityEngine.Vector2(0.0f,
					itemHeight * itemIndexFromRoot - UnityEngine.Screen.currentResolution.height / 4));
			}

			//Restore the tree's expansion status
			AkWwiseProjectInfo.GetData().ExpandedItems = expandedItemsBackUp;
		}
	}
}
#endif
